<?PHP
/**
 * OpenStation
 *
 * @Application : functions.web.php
 * @Encode : 65001 Unicode ( UTF-8 NO BOM )
 * @Description : 内置基础函数库( WEB )
 * @Author : HK <hkyyang@gmail.com>
 */


/**
 * JUMP函数，跳转
 *
 * @param String : $url
 * @param Integer : $timeout, 延迟跳转(秒)
 * @param String : $message, 消息
 * @return void
 */
function JUMP( $url = NULL, $timeout = 0, $message = NULL ) {

    $charset = auto_get_config( 'LANGUAGE.CHARSET' );
    if( empty( $message ) ) {
        $message = "系统将在 <span id=\"Timeout\">{$timeout}</span> 秒后跳转到 <a href=\"{$url}\">{$url}</a>\n";
        $message .= '<script type="text/javascript">setTimeout( timeout, 1000 ); function timeout() { var TO = document.getElementById( \'Timeout\' ); var n = parseInt( TO.innerHTML ); if( n < 1 ) return false; TO.innerHTML = n - 1; setTimeout( timeout, 1000 ); }</script>';
    }
    if( headers_sent() ) {
        echo "<meta http-equiv=\"content-type\" content=\"text/html; charset={$charset}\" />\n<meta http-equiv='Refresh' content='{$timeout};URL={$url}'>";
        if( $timeout > 0 ) {
            echo "\n{$message}";
        }
    } else {
        header( "Content-type: text/html; charset={$charset}" );
        if( $timeout <= 0 ) {
            header( "Location: {$url}" );
        } else {
            header( "refresh:{$timeout};url={$url}" );
            echo $message;
        }
    }
    exit;
}

/**
 * URL 函数，根据当前的路由模式生成URL
 *
 * @param String | Array : $param, 参数字符串或数组, 按顺序
 * @param String : $entrance, 入口文件名或文件名, 默认为当前项目入口
 * @param String : $group, 其它项目组(目录), 默认当前项目目录
 * @param Boolean : $SSL
 * @return String
 */
function URL( $param = NULL, $entrance = NULL, $group = NULL, $SSL = FALSE ) {

    if( ! empty( $group ) ) {
        $path = dirname( Cache :: get( 'HTTP.ROOT' ) ) . string_prepend_replace( string_append_replace( $group, '/' ), '/' );
    } else {
        $path = Cache :: get( 'HTTP.ROOT' );
    }

    if( empty( $entrance ) ) {
        $entrance = Cache :: get( 'SERVER.ENTRANCE' );
    } else {
        $entrance = string_append_replace( $entrance, '.php' );
    }

    $entrance = $path . $entrance;

    if( is_null( $param ) ) {
        $param = '';
    } else if( is_string( $param ) ) {
        $param = trim( $param, Cache :: get( 'OPENSTATION.URL.PATHINFO_DEPR' ) );
    } else if( is_array( $param ) ) {
        $param = implode( Cache :: get( 'OPENSTATION.URL.PATHINFO_DEPR' ), $param );
    }

    switch( Cache :: get( '@.MAIN.URL_MODE' ) ) {
        case URL_NORMAL :
            $entrance .= '?' . $param;
            break;
        case URL_PATHINFO :
            $entrance .= Cache :: get( 'OPENSTATION.URL.PATHINFO_DEPR' ) . $param;
            break;
        case URL_REWRITE :
            if( strpos( $entrance, 'index.php' ) !== FALSE ) {
                $entrance = string_append_replace( dirname( $entrance ), Cache :: get( 'OPENSTATION.URL.PATHINFO_DEPR' ) ) . $param;
            } else {
                $entrance .= Cache :: get( 'OPENSTATION.URL.PATHINFO_DEPR' ) . $param;
            }
            break;
        case URL_AUTO :
            $entrance .= '?' . Cache :: get( 'OPENSTATION.URL.PATHINFO_AUTONAME' ) . '=' . $param;
            break;
    }
    $entrance = string_after_remove( $entrance, '/' );
    if( $SSL && substr( $entrance, 0, 5 ) == 'http:' ) {
        $entrance = 'https:' . substr( $entrance, 5 );
    }
    return $entrance;

}

/**
 * 输出错误
 *
 * @param String | Array : $e, 错误信息
 * @param Boolean : $exception, 异常
 * @return void
 */
function halt( $e, $exception = FALSE ) {
    if( is_array( $e ) ) {
        $message = $e[ 'message' ] . ' in ' . basename( $e[ 'file' ] ) . ' on line ' . $e[ 'line' ];
    } else {
        $message = $e;
    }
    Log :: error( $message );
    // AJAX 请求
    if( Cache :: get( 'HTTP.AJAX' ) ) {
        if( Cache :: get( '@.ERROR.DEBUG' ) ) {
            exit( '{"error":"' . $message . '"}' );
        } else {
            exit( '{"error":""}' );
        }
    }

    if( ! $exception ) {
        Cache :: append( 'SERVER.ERROR', $e );
    // 开启了调试，显示异常，错误和警告会累加显示
    } else if( Cache :: get( '@.ERROR.DEBUG' ) ) {
        include Cache :: get( 'OPENSTATION.ERROR.EXCEPTION' );
    // 异常行为没有开启调试，但开启了500页面
    } else if( Cache :: get( '@.ERROR.EXCEPTION_JUMP' ) ) {
        include Cache :: get( 'OPENSTATION.ERROR.ERROR_500' );
    // 否则影响中断的错误或异常只显示空白页面
    } else {
        exit;
    }
}

/**
 * 抛出异常信息
 *
 * @param String : $error, 异常信息
 * @param String : $type, 异常类型
 * @param Integer : $code, 异常代码
 * @return void
 */
function throw_exception( $error, $type='OSException', $code = 0 ) {
    if( is_array( $error ) ) {
        $msg = $error[ 'message' ];
        $extra = isset( $error[ 'extra' ] ) ? ( Boolean ) $error[ 'extra' ] : FALSE;
    } else {
        $msg = $error;
    }
    if( $type == 'OSException' ) {
        $extra = TRUE;
    }
    // 自动日志记录
    Log :: error( $msg );
    // AJAX请求
    if( Cache :: get( 'HTTP.AJAX' ) ) {
        exit( '{"error":"' . $msg . '"}' );
    }
    // 异常类不存在
    if( ! class_exists( $type, FALSE ) ) {
        exit( $msg );
    }
    // 未开启调试，显示500错误
    if( ! Cache :: get( '@.ERROR.DEBUG' ) ) {
        if( Cache :: get( 'HTTP.AJAX' ) ) {
            exit( '{"error":"' . $msg . '"}' );
        }
    }
    throw new $type( $error, $code, $extra );
}

/**
 * Notfound
 *
 * @param $
 * @return void
 */
function notfound( $jump = TRUE ) {
    Log :: error( '404 Not Found' );
    switch( Cache :: get( '@.ERROR.NOT_ACTION_JUMP' ) ) {
        // 跳转首页，复制默认的方法到现在执行的行为方法
        case 1 :
            Cache :: set( 'SERVER.METHOD', 'index' );
            if( $jump ) {
                JUMP( URL() );
            }
            break;
        // 跳转404页面
        case 2 :
            include Cache :: get( 'OPENSTATION.ERROR.ERROR_404' );
            break;
        default :
            if( ! headers_sent() ) {
                if( IS_CGI ) {
                    header( 'Status: 404 Not Found');
                } else {
                    header( 'HTTP/1.1 404 Not Found' );
                }
            }
    }
    if( $jump ) {
        exit;
    }
}

/**
 * 获取客户端IP地址
 *
 * @param $
 * @return String
 */
function get_ip() {
    if( getenv( 'HTTP_CLIENT_IP' ) && strcasecmp( getenv( 'HTTP_CLIENT_IP' ), 'unknown' ) ) {
        $ip = getenv( 'HTTP_CLIENT_IP' );
    } else if( getenv( 'HTTP_X_FORWARDED_FOR' ) && strcasecmp( getenv( 'HTTP_X_FORWARDED_FOR' ), 'unknown' ) ) {
        $ip = getenv( 'HTTP_X_FORWARDED_FOR' );
    } else if( getenv( 'REMOTE_ADDR' ) && strcasecmp( getenv( 'REMOTE_ADDR' ), 'unknown' ) ) {
        $ip = getenv( 'REMOTE_ADDR' );
    } else if( isset( $_SERVER[ 'REMOTE_ADDR' ] ) && $_SERVER[ 'REMOTE_ADDR' ] && strcasecmp( $_SERVER[ 'REMOTE_ADDR' ], 'unknown' ) ) {
        $ip = $_SERVER[ 'REMOTE_ADDR' ];
    } else {
        $ip = 'N/A';
    }
    return $ip;
}

/**
 * 获取客户端详细信息
 *
 * @param $
 * @return Array
 */
function get_client_info() {
    $client = array();
    $user_agent = $_SERVER[ 'HTTP_USER_AGENT' ];
    // 客户端IP地址
    $client[ 'ip' ] = get_ip();
    $client[ 'mobile' ] = FALSE;
    // 判断手机访问
    switch( TRUE ) :
        // Apple/iPhone browser renders as mobile
        case ( preg_match( '/(apple|iphone|ipod)/i', $user_agent ) && preg_match( '/mobile/i', $user_agent ) ):
            $client[ 'mobile' ] = TRUE;
        break;
        // Other mobile browsers render as mobile
        case ( preg_match( '/(blackberry|configuration\/cldc|hp |hp-|htc |htc_|htc-|iemobile|kindle|midp|mmp|motorola|mobile|nokia|opera mini|opera mobi|palm|palmos|pocket|portalmmm|ppc;|smartphone|sonyericsson|sqh|spv|symbian|treo|up.browser|up.link|vodafone|windows ce|xda |xda_)/i', $user_agent ) ):
            $client[ 'mobile' ] = TRUE;
        break;
        // Wap browser
        case ( ( ( strpos( strtolower( $_SERVER[ 'HTTP_ACCEPT' ] ), 'text/vnd.wap.wml' ) > 0 ) || ( strpos( strtolower( $_SERVER[ 'HTTP_ACCEPT' ] ), 'application/vnd.wap.xhtml+xml' )>0) ) || ( ( isset( $_SERVER[ 'HTTP_X_WAP_PROFILE' ] ) || isset( $_SERVER[ 'HTTP_PROFILE' ] ) ) ) ):
            $client[ 'mobile' ] = TRUE;
        break;
        // Shortend user agents
        case ( in_array( strtolower( substr( $user_agent, 0, 3 ) ), array( 'lg ' => 'lg ', 'lg-' => 'lg-', 'lg_' => 'lg_', 'lge' => 'lge' ) ) );
            $client[ 'mobile' ] = TRUE;
        break;
        // More shortend user agents
        case ( in_array( strtolower( substr( $user_agent, 0, 4 ) ), array( 'acs-' => 'acs-', 'amoi' => 'amoi', 'doco' => 'doco', 'eric' => 'eric', 'huaw' => 'huaw', 'lct_' => 'lct_', 'leno' => 'leno', 'mobi' => 'mobi', 'mot-' => 'mot-', 'moto' => 'moto', 'nec-' => 'nec-', 'phil' => 'phil', 'sams' => 'sams', 'sch-' => 'sch-', 'shar' => 'shar', 'sie-' => 'sie-', 'wap_' => 'wap_', 'zte-' => 'zte-' ) ) );
            $client[ 'mobile' ] = TRUE;
        break;
        // Render mobile site for mobile search engines
        case ( preg_match( '/Googlebot-Mobile/i', $user_agent ) || preg_match( '/YahooSeeker\/M1A1-R2D2/i', $user_agent ) ):
            $client[ 'mobile' ] = TRUE;
        break;
    endswitch;
    // 获取操作系统
    switch( TRUE ) {
        // Microsoft Windows
        case ( stripos( $user_agent, 'win' ) ):
            $client[ 'os' ] = 'Windows';
            switch( TRUE ):
                case ( strpos( $user_agent, '95' ) ):
                    $client[ 'os' ] .= ' 95';
                break;
                case ( strpos( $user_agent, '4.90' ) ):
                    $client[ 'os' ] .= ' ME';
                break;
                case ( strpos( $user_agent, '98' ) ):
                    $client[ 'os' ] .= ' 98';
                break;
                case ( stripos( $user_agent, 'NT 5.0' ) ):
                    $client[ 'os' ] .= ' 2000';
                break;
                case ( stripos( $user_agent, 'NT 5.1' ) ):
                    $client[ 'os' ] .= ' XP';
                break;
                case ( stripos( $user_agent, 'NT 5.2' ) ):
                    $client[ 'os' ] .= ' Server 2003';
                break;
                case ( stripos( $user_agent, 'NT 6.0' ) ):
                    $client[ 'os' ] .= ' Vista';
                break;
                case ( stripos( $user_agent, 'NT 6.1' ) ):
                    $client[ 'os' ] .= ' 7';
                break;
                case ( stripos( $user_agent, '32' ) ):
                    $client[ 'os' ] .= ' 32';
                break;
                case ( stripos( $user_agent, 'NT' ) ):
                    $client[ 'os' ] .= ' NT';
                break;
            endswitch;
        break;
        // Mac OS
        case ( stripos( $user_agent, 'Mac OS' ) ):
            $client[ 'os' ] = 'Mac OS';
        break;
        // Linux
        case ( stripos( $user_agent, 'Linux' ) ):
            $client[ 'os' ] = 'Linux';
        break;
        // Unix
        case ( stripos( $user_agent, 'Unix' ) ):
            $client[ 'os' ] = 'Unix';
        break;
        case ( stripos( $user_agent, 'Sun' ) ):
            $client[ 'os' ] = 'SunOS';
        break;
        default :
            $client[ 'os' ] = 'N/A';
        break;
    }
    $ver = array();
    // 浏览器
    switch( TRUE ) {
        case ( preg_match( '/MSIE\s([0-9].[0-9]{1,2})/i', $user_agent, $ver ) ):
            $client[ 'browser' ] = 'Internet Explorer ' . $ver[ 1 ];
        break;
        case ( preg_match( '/Opera\/([0-9]{1,2}.[0-9]{1,2})/i', $user_agent, $ver ) ):
            $client[ 'browser' ] = 'Opera ' . $ver[ 1 ];
        break;
        case ( preg_match( '/Firefox\/([0-9.]{1,5})/i', $user_agent, $ver ) ):
            $client[ 'browser' ] = 'Firefox ' . $ver[ 1 ];
        break;
        case ( preg_match( '/Chrome\/([0-9]{1,3})/i', $user_agent, $ver ) ):
            $client[ 'browser' ] = 'Chrome ' . $ver[ 1 ];
        break;
        case ( preg_match( '/Safari\/([0-9.]{1,3})/i', $user_agent, $ver ) ):
            $client[ 'browser' ] = 'Safari ' . $ver[ 1 ];
        break;
        default:
            $client[ 'browser' ] = 'N/A';
        break;
    }
    return $client;
}

?>